/**
 * IndexedDB服务，用于存储和获取模型数据
 * 基于 https://juejin.cn/post/7026900352968425486 实现
 */
import type { MapDataItem } from "./extractModelData";

// 数据库配置
const DB_CONFIG = {
  DB_NAME: "MapModelDB", // 数据库名称
  STORE_NAME: "modelData", // 存储对象名称
  VERSION: 1, // 数据库版本
};

/**
 * 打开或创建IndexedDB数据库
 * @returns Promise<IDBDatabase> 数据库实例
 */
export const openDB = (): Promise<IDBDatabase> => {
  return new Promise((resolve, reject) => {
    // 兼容浏览器
    const indexedDB =
      window.indexedDB ||
      (window as any).mozIndexedDB ||
      (window as any).webkitIndexedDB ||
      (window as any).msIndexedDB;

    if (!indexedDB) {
      reject(new Error("浏览器不支持IndexedDB"));
      return;
    }

    // 打开数据库，若没有则会创建
    const request = indexedDB.open(DB_CONFIG.DB_NAME, DB_CONFIG.VERSION);

    // 数据库打开成功回调
    request.onsuccess = function (event) {
      console.log("IndexedDB数据库打开成功");
      resolve((event.target as any)?.result);
    };

    // 数据库打开失败的回调
    request.onerror = function (event) {
      console.error("IndexedDB数据库打开失败:", event);
      reject(event);
    };

    // 数据库有更新时候的回调
    request.onupgradeneeded = function (event) {
      console.log("IndexedDB数据库需要更新");
      const db = (event.target as any)?.result;

      // 如果不存在模型数据仓库，则创建
      if (!db.objectStoreNames.contains(DB_CONFIG.STORE_NAME)) {
        const objectStore = db.createObjectStore(DB_CONFIG.STORE_NAME, {
          keyPath: "id", // 使用id作为主键
        });
        // 创建索引以便于查询
        objectStore.createIndex("name", "name", { unique: false });
        objectStore.createIndex("modelExist", "modelExist", { unique: false });
        objectStore.createIndex("lon", "lon", { unique: false });
        objectStore.createIndex("lat", "lat", { unique: false });
        console.log("IndexedDB数据仓库创建成功");
      }
    };
  });
};

/**
 * 存储数据到IndexedDB
 * @param data 要存储的数据数组
 * @returns Promise<void>
 */
export const saveDataToIndexedDB = async (
  data: MapDataItem[]
): Promise<void> => {
  try {
    const db = await openDB();
    const transaction = db.transaction([DB_CONFIG.STORE_NAME], "readwrite");
    const objectStore = transaction.objectStore(DB_CONFIG.STORE_NAME);

    // 清空现有的数据
    await new Promise<void>((resolve, reject) => {
      const clearRequest = objectStore.clear();
      clearRequest.onsuccess = () => resolve();
      clearRequest.onerror = (event) => reject(event);
    });

    // 存储新数据
    const storePromises = data.map((item) => {
      return new Promise<void>((resolve, reject) => {
        const request = objectStore.add(item);
        request.onsuccess = () => resolve();
        request.onerror = (event) => reject(event);
      });
    });

    await Promise.all(storePromises);
    console.log(`IndexedDB存储数据成功，共存储${data.length}条记录`);
  } catch (error) {
    console.error("IndexedDB存储数据失败:", error);
    throw error;
  }
};

/**
 * 从IndexedDB获取所有数据
 * @returns Promise<MapDataItem[]> 获取的数据数组
 */
export const getAllDataFromIndexedDB = async (): Promise<MapDataItem[]> => {
  try {
    const db = await openDB();
    const transaction = db.transaction([DB_CONFIG.STORE_NAME], "readonly");
    const objectStore = transaction.objectStore(DB_CONFIG.STORE_NAME);

    return new Promise((resolve, reject) => {
      const request = objectStore.getAll();
      request.onsuccess = function (event) {
        const data = (event.target as any)?.result as MapDataItem[];
        console.log(`IndexedDB获取数据成功，共获取${data.length}条记录`);
        resolve(data);
      };
      request.onerror = function (event) {
        console.error("IndexedDB获取数据失败:", event);
        reject(event);
      };
    });
  } catch (error) {
    console.error("IndexedDB操作失败:", error);
    throw error;
  }
};

/**
 * 检查IndexedDB中是否有数据
 * @returns Promise<boolean> 是否有数据
 */
export const hasDataInIndexedDB = async (): Promise<boolean> => {
  try {
    const db = await openDB();
    const transaction = db.transaction([DB_CONFIG.STORE_NAME], "readonly");
    const objectStore = transaction.objectStore(DB_CONFIG.STORE_NAME);

    return new Promise((resolve) => {
      const countRequest = objectStore.count();
      countRequest.onsuccess = function (event) {
        const count = (event.target as any)?.result;
        resolve(count > 0);
      };
      countRequest.onerror = function () {
        resolve(false);
      };
    });
  } catch (error) {
    console.error("检查IndexedDB数据失败:", error);
    return false;
  }
};

/**
 * 删除IndexedDB数据库
 * @returns Promise<void>
 */
export const deleteIndexedDB = async (): Promise<void> => {
  return new Promise((resolve, reject) => {
    const request = window.indexedDB.deleteDatabase(DB_CONFIG.DB_NAME);
    request.onsuccess = () => {
      console.log("IndexedDB数据库删除成功");
      resolve();
    };
    request.onerror = (event) => {
      console.error("IndexedDB数据库删除失败:", event);
      reject(event);
    };
  });
};
